#include"thread.h"
#include"log.h"

namespace sylar{

/// 线程局部变量,线程开始时初始化，结束时释放
static thread_local Thread* t_thread = nullptr;
static thread_local std::string t_thread_name = "UNKNOWN";

/// 所有系统级别的日志都放在system
static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");


Semaphore::Semaphore(uint32_t count){
    if(sem_init(&m_semaphore, 0, count)){
        throw std::logic_error("sem_init error");
    }
}
Semaphore::~Semaphore(){
    sem_destroy(&m_semaphore);
}
void Semaphore::wait(){
    //信号量减1
    if(sem_wait(&m_semaphore)){
        throw std::logic_error("sem_wait error");
    }

}
void Semaphore::notify(){
    //信号量加1
    if(sem_post(&m_semaphore)){
        throw std::logic_error("sem_post error");
    }
}


Thread* Thread::GetThis(){
    return t_thread;
}
/// 提供给日志
const std::string& Thread::GetName(){
    return t_thread_name;
}

void Thread::SetName(const std::string& name){
    if(name.empty()){
        return;
    }
    if(t_thread){
    t_thread->m_name = name;
    }
    t_thread_name = name;
}

void* Thread::run(void* arg){
    Thread* thread = (Thread*) arg;
    /// 赋值给线程局部变量
    t_thread = thread;
    t_thread_name = thread->m_name;
    /// 设置全局唯一线程id
    thread->m_id = sylar::GetThreadId();
    // 设置线程名称，可以在top内看到
    pthread_setname_np(pthread_self(), thread->m_name.substr(0, 15).c_str());
 
    std::function<void()> cb;
    cb.swap(thread->m_cb);
    // 通知构造函数，线程初始化好了
    t_thread->m_semaphore.notify();
    cb();
    return 0;
}

Thread::Thread(std::function<void()> cb, const std::string&  name)
    :m_cb(cb), m_name(name){
    /// 回调函数和命名的初始化
     if(name.empty()){
         m_name = "UNKNOWN";
     }
     int rt = pthread_create(&m_thread, nullptr, &Thread::run, this);
     if(rt){
            SYLAR_LOG_ERROR(g_logger) << "pthread_create thread fail, rt=" << rt
                            << " name=" << m_name;
            throw std::logic_error("pthread_create error");
     }
    SYLAR_LOG_INFO(g_logger) << "thread ctor start=" << m_name;
     // 保证确定pthread_create创建的线程已经执行了，所以先等待一下
     m_semaphore.wait();   
}

Thread::~Thread(){
    // join和detach只能二选一
    if(m_thread){
        pthread_detach(m_thread);
    }
    SYLAR_LOG_INFO(g_logger) << "thread dtor=" << m_name;
}

void Thread::join(){
    if(m_thread){
        int rt = pthread_join(m_thread, nullptr);
//        int rt = pthread_detach(m_thread);
        if(rt){
            SYLAR_LOG_ERROR(g_logger) << "pthread_join thread fail, rt=" << rt
                            << " name=" << m_name;
            throw std::logic_error("pthread_join error");
        }
        m_thread = 0;
    }

}


}